package com.authine.cloudpivot.ext.applicationservice.report;

import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.dto.ImportFileVO;
import com.authine.cloudpivot.ext.enums.inquiry.InquiryStatusEnum;
import com.authine.cloudpivot.ext.enums.inquiry.QuotationStatusEnum;
import com.authine.cloudpivot.ext.model.ReportRecord;
import com.authine.cloudpivot.ext.utils.BoServiceUtils;
import com.authine.cloudpivot.ext.utils.BoUtils;
import com.authine.cloudpivot.ext.utils.RegexUtils;
import com.authine.cloudpivot.ext.utils.system.ReportUtils;
import com.authine.common.util.DateUtils;
import com.authine.hermes.app.file.dto.clientobject.DownLoadDTO;
import com.authine.hermes.app.file.feign.FtpFeignServiceI;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import com.authine.mvp.app.launcher.dto.errorcode.ErrorCodeEnum;
import com.authine.mvp.app.launcher.utils.ModelRuntimeException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.util.StringUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

/**
 * @ClassName QuotationReportService
 * @Description: 我的报价导出
 * @Author fj
 * @Date 2021/9/10
 * @Version V1.0
 **/
@Path("QuotationReportService")
@Slf4j
public class QuotationReportService {
    /**
     * 我的报价-待参与-Excel报价导出
     *
     * @param record 报表导出数据
     * @return 导出
     */
    @Path("importQuotationTemplateReport")
    @POST
    @Operation(summary = "我的报价-待参与-Excel报价导出", tags = CUSTOM_SERVICE)
    public SingleResponse<BO> importQuotationTemplateReport(@Parameter ReportRecord record) {
        if (StringUtils.isEmpty(record.getType())) {
            throw new BizException("报表导出类型不正确");
        }
        if (StringUtils.isEmpty(record.getCode())) {
            throw new BizException("报表导出文件不正确");
        }
        List<Map<String, Object>> reportList = Lists.newArrayList();// 报表数据
        // 通过报价商品id获取报价商品列表
        SingleResponse<BOList> quotationGoodsBOList = BoServiceUtils.findListByIn(ModelConst.T_QUOTATION_GOODS, "id", record.getIds());
        log.info("-----------------------通过报价商品id获取报价商品列表：{}------------------------", JSONObject.toJSONString(quotationGoodsBOList));
        if (quotationGoodsBOList.getData().getTotal() > 0) {
            Map<String, Object> dataMap;
            for (Map<String, Object> quotationMap : quotationGoodsBOList.getData().getData()) {
                dataMap = Maps.newHashMap();
                dataMap.put("id", String.valueOf(quotationMap.get("id")));
                dataMap.put("inquiryGoodsId", String.valueOf(quotationMap.get("inquiry_goods_id")));
                dataMap.put("maximum", quotationMap.get("num") == null ? 0d : ((BigDecimal) quotationMap.get("num")).doubleValue());
                dataMap.put("name", String.valueOf(quotationMap.get("name")));
                dataMap.put("brand", String.valueOf(quotationMap.get("brand")));
                dataMap.put("model", String.valueOf(quotationMap.get("model")));
                reportList.add(dataMap);
            }
        }
        return ReportUtils.exportReport(record.getCode(), record.getType(), reportList);
    }

    /**
     * 我的报价-待报价-导出
     *
     * @param record 报表导出数据
     * @return 导出
     */
    @Path("notQuotedGoodsReport")
    @POST
    @Operation(summary = "我的报价-待报价-导出", tags = CUSTOM_SERVICE)
    public SingleResponse<BO> notQuotedGoodsReport(@Parameter ReportRecord record) {
        if (StringUtils.isEmpty(record.getType())) {
            throw new BizException("报表导出类型不正确");
        }
        if (StringUtils.isEmpty(record.getCode())) {
            throw new BizException("报表导出文件不正确");
        }
        List<Map<String, Object>> reportList = Lists.newArrayList();// 报表数据
        // 通过报价商品id获取报价商品列表
        SingleResponse<BOList> quotationGoodsBOList = BoServiceUtils.findListByIn(ModelConst.T_QUOTATION_GOODS, "id", record.getIds());
        log.info("-----------------------通过报价商品id获取报价商品列表：{}------------------------", JSONObject.toJSONString(quotationGoodsBOList));
        if (quotationGoodsBOList.getData().getTotal() > 0) {
            Map<String, Object> dataMap;
            SingleResponse<BO> inquiryGoodsLoadBO;
            for (Map<String, Object> quotationMap : quotationGoodsBOList.getData().getData()) {
                inquiryGoodsLoadBO = BoServiceUtils.loadBo(String.valueOf(quotationMap.get("inquiry_goods_id")), ModelConst.T_INQUIRY_GOODS);
                log.info("-----------------------根据询价商品id获取询价商品信息：{}------------------------", JSONObject.toJSONString(inquiryGoodsLoadBO));
                dataMap = Maps.newHashMap();
                dataMap.put("id", String.valueOf(quotationMap.get("id")));
                dataMap.put("inquiryGoodsId", String.valueOf(quotationMap.get("inquiry_goods_id")));
                dataMap.put("name", String.valueOf(quotationMap.get("name")));
                dataMap.put("brand", String.valueOf(quotationMap.get("brand")));
                dataMap.put("model", String.valueOf(quotationMap.get("model")));
                dataMap.put("spec", quotationMap.get("spec") == null ? "" : String.valueOf(quotationMap.get("spec")));
                dataMap.put("price", quotationMap.get("price") == null ? 0d : ((BigDecimal) quotationMap.get("price")).doubleValue());
                dataMap.put("amount", quotationMap.get("amount") == null ? 0d : ((BigDecimal) quotationMap.get("price")).doubleValue());
                dataMap.put("pretaxPrice", quotationMap.get("pretax_price") == null ? 0d : ((BigDecimal) quotationMap.get("pretax_price")).doubleValue());
                dataMap.put("delivery", quotationMap.get("delivery") == null ? 0 : ((BigDecimal) quotationMap.get("delivery")).intValue());
                dataMap.put("num", quotationMap.get("num") == null ? 0d : ((BigDecimal) quotationMap.get("num")).doubleValue());
                dataMap.put("unit", quotationMap.get("unit") == null ? "" : String.valueOf(quotationMap.get("unit")));
                dataMap.put("status", Objects.requireNonNull(QuotationStatusEnum.get(String.valueOf(quotationMap.get("quotation_goods_status")))).getDes());
                dataMap.put("freight", quotationMap.get("freight") == null ? 0d : ((BigDecimal) quotationMap.get("freight")).doubleValue());
                dataMap.put("remarkMessage", quotationMap.get("remark_message") == null ? "" : String.valueOf(quotationMap.get("remark_message")));
                dataMap.put("total", quotationMap.get("total") == null ? 0d : ((BigDecimal) quotationMap.get("total")).doubleValue());
                dataMap.put("quoteCount", inquiryGoodsLoadBO.getData().getData().get("quote_count") == null ? 0 : ((BigDecimal) inquiryGoodsLoadBO.getData().getData().get("quote_count")).intValue());
                dataMap.put("partakeCount", inquiryGoodsLoadBO.getData().getData().get("partake_count") == null ? 0 : ((BigDecimal) inquiryGoodsLoadBO.getData().getData().get("partake_count")).intValue());
                dataMap.put("inquiryId", String.valueOf(inquiryGoodsLoadBO.getData().getData().get("inquiry_id")));
                dataMap.put("inquiryGoodsStatus", Objects.requireNonNull(InquiryStatusEnum.get(String.valueOf(inquiryGoodsLoadBO.getData().getData().get("inquiry_goods_status")))).getDes());
                dataMap.put("address", quotationMap.get("address") == null ? "" : String.valueOf(quotationMap.get("address")));
                dataMap.put("description", quotationMap.get("description") == null ? "" : String.valueOf(quotationMap.get("description")));
                dataMap.put("memo", inquiryGoodsLoadBO.getData().getData().get("memo") == null ? "" : String.valueOf(inquiryGoodsLoadBO.getData().getData().get("memo")));
                dataMap.put("time", String.valueOf(quotationMap.get("createdTime")));
                reportList.add(dataMap);
            }
        }
        return ReportUtils.exportReport(record.getCode(), record.getType(), reportList);
    }

    /**
     * 我的报价-待报价-Excel报价导入
     *
     * @param importFileVO 导入文件id
     * @return 导出
     */
    @Path("importQuotationTemplate")
    @POST
    @Operation(summary = "我的报价-待报价-Excel报价导入", tags = CUSTOM_SERVICE)
    public SingleResponse<List<Map<String, Object>>> importQuotationTemplate(@Parameter ImportFileVO importFileVO) {
        if (StringUtils.isEmpty(importFileVO.getRefId())) {
            throw new ModelRuntimeException(ErrorCodeEnum.BIZ_PARAMS_ERR, "文件id不存在");
        }

        // 获取文件下载流
        FtpFeignServiceI ftpFeignServiceI = ApplicationContextUtils.getBean(FtpFeignServiceI.class);
        SingleResponse<DownLoadDTO> response = ftpFeignServiceI.downloadBytes(importFileVO.getRefId());
        if (response.getData() == null) {
            throw BoUtils.bizException("文件流数据为空");
        }

        // 字节数组转为输入流
        InputStream inputStream = new ByteArrayInputStream(response.getData().getImageBytes());
        List<Map<String, Object>> dataList = Lists.newArrayList();
        Map<String, Object> dataMap;
        try {
            // 创建excel工作簿
            Workbook workbook = WorkbookFactory.create(inputStream);
            Row row;
            Sheet firstSheet = workbook.getSheetAt(0);
            if (firstSheet.getPhysicalNumberOfRows() < 2) {
                throw new BizException("导入的excel文件没有报价信息，请选择正确的excel进行导入");
            }
            for (int rowNum = 1; rowNum < firstSheet.getPhysicalNumberOfRows(); rowNum++) {
                row = firstSheet.getRow(rowNum);
                dataMap = Maps.newHashMap();
                // 报价商品单号
                String id = getValue(row.getCell(0));
                if (!StringUtils.isEmpty(id)) {
                    if (!RegexUtils.check(RegexUtils.Type.IS_INTEGER_POSITIVE, id)) {
                        throw new BizException("excel第" + rowNum + "行异常:报价单号必须为正整数！");
                    }
                }
                dataMap.put("id", id);

                // 询价商品单号
                String inquiryGoodsId = getValue(row.getCell(1));
                if (!StringUtils.isEmpty(inquiryGoodsId)) {
                    if (!RegexUtils.check(RegexUtils.Type.IS_INTEGER_POSITIVE, inquiryGoodsId)) {
                        throw new BizException("excel第" + rowNum + "行异常:询价商品单号必须为正整数！");
                    }
                }
                dataMap.put("inquiry_goods_id", inquiryGoodsId);

                // 报价有效期
                String expireDayStr = getValue(row.getCell(2));
                if (!StringUtils.isEmpty(expireDayStr)) {
                    Date expire = DateUtil.getJavaDate(Double.parseDouble(expireDayStr));
                    try {
                        dataMap.put("expire", DateUtils.format(expire, DateUtils.TIMESTAMP_PATTERN));
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new BizException("excel第" + rowNum + "行异常:请输入正确日期yyyy-MM-dd HH:mm:ss！");
                    }
                } else {
                    throw new BizException("excel第" + rowNum + "行异常:报价有效期为必填");
                }

                // 未税单价
                String pretaxPriceStr = getValue(row.getCell(3));
                if (!StringUtils.isEmpty(pretaxPriceStr)) {
                    if (RegexUtils.check(RegexUtils.Type.IS_NUMBER_POSITIVE, pretaxPriceStr)) {
                        dataMap.put("pretax_price", new BigDecimal(pretaxPriceStr));
                    } else {
                        throw new BizException("excel第" + rowNum + "行异常:未税单价必须为正数！");
                    }
                } else {
                    throw new BizException("excel第" + rowNum + "行异常:未税单价为必填");
                }

                // 最长货期(天)
                String deliveryStr = getValue(row.getCell(4));
                if (!StringUtils.isEmpty(deliveryStr)) {
                    if (RegexUtils.check(RegexUtils.Type.IS_INTEGER_POSITIVE, deliveryStr)) {
                        dataMap.put("delivery", Integer.valueOf(deliveryStr));
                    } else {
                        throw new BizException("excel第" + rowNum + "行异常:货期必须为正整数！");
                    }
                } else {
                    throw new BizException("excel第" + rowNum + "行异常:最长货期为必填");
                }

                // 发货地
                String address = getValue(row.getCell(5));
                if (!StringUtils.isEmpty(address)) {
                    if (address.length() > 500) {
                        throw new BizException("excel第" + rowNum + "行异常:地址长度不可超过500字符！");
                    } else {
                        dataMap.put("address", address);
                    }
                } else {
                    throw new BizException("excel第" + rowNum + "行异常:发货地为必填");
                }


                // 最大订货库存
                String maximumStr = getValue(row.getCell(6));
                if (!StringUtils.isEmpty(maximumStr)) {
                    if (RegexUtils.check(RegexUtils.Type.IS_NUMBER_POSITIVE, maximumStr)) {
                        dataMap.put("maximum", new BigDecimal(maximumStr));
                    } else {
                        throw new BizException("excel第" + rowNum + "行异常:最大订货库存必须为正数！");
                    }
                } else {
                    throw new BizException("excel第" + rowNum + "行异常:最大订货库存为必填");
                }

                // 询价商品名称
                String name = getValue(row.getCell(7));
                if (!StringUtils.isEmpty(name) && name.length() > 500) {
                    throw new BizException("excel第" + rowNum + "行异常:商品长度不可超过500字符！");
                } else {
                    dataMap.put("name", name);
                }

                // 品牌
                String brand = getValue(row.getCell(8));
                if (!StringUtils.isEmpty(brand) && brand.length() > 500) {
                    throw new BizException("excel第" + rowNum + "行异常:品牌长度不可超过500字符！");
                } else {
                    dataMap.put("brand", brand);
                }

                // 型号
                String model = getValue(row.getCell(9));
                if (!StringUtils.isEmpty(model) && model.length() > 500) {
                    throw new BizException("excel第" + rowNum + "行异常:型号长度不可超过500字符！");
                } else {
                    dataMap.put("model", model);
                }
                dataList.add(dataMap);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new BizException("导入的excel文件格式不正确，请选择正确的excel进行导入");
        }
        return SingleResponse.of(dataList);
    }

    /**
     * 获取excel列数据
     *
     * @param cell 列信息
     * @return 数据信息
     */
    private String getValue(Cell cell) {
        String ret = "";
        if (null != cell) {
            cell.setCellType(CellType.STRING);
            ret = cell.getStringCellValue();
        }
        return ret;
    }
}
